import warnings
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
from matplotlib.font_manager import FontProperties
from sklearn.tree import export_graphviz
import graphviz
from sklearn.model_selection import train_test_split
from sklearn.linear_model import LinearRegression
import sklearn.metrics as metrics
from sklearn.tree import DecisionTreeClassifier
from sklearn.ensemble import RandomForestClassifier

warnings.filterwarnings("ignore", category=UserWarning)

data = pd.read_csv('./data/data.csv')
x_var_list = ['vehicle_year', 'vehicle_make', 'bankruptcy_ind', 'tot_derog', 'tot_tr', 'age_oldest_tr',
              'tot_open_tr', 'tot_rev_tr', 'tot_rev_debt', 'tot_rev_line', 'rev_util', 'fico_score', 'purch_price',
              'msrp', 'down_pyt', 'loan_term', 'loan_amt', 'ltv', 'tot_income', 'veh_mileage', 'used_ind', 'weight']
data_x = data.loc[:, x_var_list]
data_y = data.loc[:, 'bad_ind']
data_x["tot_income"] = data_x["tot_income"].fillna(data_x["tot_income"].median())

q25 = data_x["tot_income"].quantile(0.25)
q75 = data_x["tot_income"].quantile(0.75)
max_qz = q75 + 1.5 * (q75 - q25)
temp_series = data_x["tot_income"] > max_qz
data_x.loc[temp_series, "tot_income"] = max_qz

data_x["tot_rev_line1"] = data_x["tot_rev_line"].fillna('unknown')
q25 = data_x["tot_rev_line"].quantile(0.25)
q75 = data_x["tot_rev_line"].quantile(0.75)
max_qz = q75 + 1.5 * (q75 - q25)
temp_series = data_x["tot_rev_line"] > max_qz
data_x.loc[temp_series, "tot_rev_line"] = max_qz

data_x["tot_rev_line_fx"] = pd.qcut(data_x["tot_rev_line"], 10, labels=False, duplicates='drop')
data_x["tot_rev_line_fx"] = data_x["tot_rev_line_fx"].fillna(999999)
data_x.loc[:, 'vehicle_year'].value_counts().sort_index()

data_x.loc[data_x.loc[:, 'vehicle_year'].isin([0, 9999]), 'vehicle_year'] = np.nan
data_x["vehicle_year"] = data_x["vehicle_year"].fillna(data_x["vehicle_year"].median())

data_x["bankruptcy_ind1"] = data_x["bankruptcy_ind"].fillna('unknown')

x_var_list = ['tot_derog', 'tot_tr', 'age_oldest_tr', 'tot_open_tr', 'tot_rev_tr', 'tot_rev_debt',
              'tot_rev_line', 'rev_util', 'fico_score', 'purch_price', 'msrp', 'down_pyt',
              'loan_term', 'loan_amt', 'ltv', 'tot_income', 'veh_mileage', 'used_ind']
data_x = data.loc[:, x_var_list]

temp = data_x.median()
temp_dict = {}
for i in range(len(list(temp.index))):
    temp_dict[list(temp.index)[i]] = list(temp.values)[i]
data_x_fill = data_x.fillna(temp_dict)
x_train, x_test, y_train, y_test = train_test_split(data_x_fill, data_y, test_size=0.25, random_state=12345)
linear = LinearRegression()
model = linear.fit(x_train, y_train)

var_coef = pd.DataFrame()
var_coef['var'] = x_var_list
var_coef['coef'] = linear.coef_

fpr, tpr, th = metrics.roc_curve(y_test, linear.predict(x_test))
roc_auc = metrics.auc(fpr, tpr)
print(f'线性回归roc_auc={roc_auc}')

font = FontProperties()
font.set_family('SimSun')
font.set_size(12)
font.set_weight('bold')
plt.plot(fpr, tpr, color='b', lw=2, label='ROC curve (area = %f)' % roc_auc)
plt.plot([0, 1], [0, 1], color='r', lw=2, linestyle='--')
plt.xlim([-0.1, 1.1])
plt.ylim([-0.1, 1.1])
plt.xlabel('假阳率', fontproperties=font)
plt.ylabel('真阳率', fontproperties=font)
plt.title('线性回归ROC曲线', fontproperties=font)
plt.legend(loc="upper left")
plt.show()

tree = DecisionTreeClassifier()
tree.fit(x_train, y_train)
print(f'默认参数树的深度为：{len(np.unique(tree.apply(x_train)))}')
fpr, tpr, th2 = metrics.roc_curve(y_test, tree.predict_proba(x_test.values)[:, 1])
roc_auc = metrics.auc(fpr, tpr)
print(f'默认参数决策树roc_auc={roc_auc}')
fig, axs = plt.subplots(nrows=2, ncols=2, figsize=(12, 7))
fig.subplots_adjust(hspace=0.4)
axs[0][0].plot(fpr, tpr, color='b', lw=2, label='ROC curve (area = %f)' % roc_auc)
axs[0][0].plot([0, 1], [0, 1], color='r', lw=2, linestyle='--')
axs[0][0].set_xlim([-0.1, 1.1])
axs[0][0].set_ylim([-0.1, 1.1])
axs[0][0].set_xlabel('假阳率', fontproperties=font)
axs[0][0].set_ylabel('真阳率', fontproperties=font)
axs[0][0].set_title('默认参数决策树ROC曲线', fontproperties=font)
axs[0][0].legend(loc="upper left")

tree2 = DecisionTreeClassifier(max_depth=20, min_samples_leaf=100)
tree2.fit(x_train, y_train)
print(f'修改参数树的深度为：{len(np.unique(tree2.apply(x_train)))}')
fpr, tpr, th3 = metrics.roc_curve(y_test, tree2.predict_proba(x_test.values)[:, 1])
roc_auc = metrics.auc(fpr, tpr)
print(f'修改参数决策树roc_auc={roc_auc}')
# 决策树结构可视化
decision_tree = export_graphviz(tree2, out_file=None, filled=True, rounded=True, special_characters=True)
tree = graphviz.Source(decision_tree, format='png')
tree.render("./data/decision_tree", view=True)

axs[0][1].plot(fpr, tpr, color='b', lw=2, label='ROC curve (area = %f)' % roc_auc)
axs[0][1].plot([0, 1], [0, 1], color='r', lw=2, linestyle='--')
axs[0][1].set_xlim([-0.1, 1.1])
axs[0][1].set_ylim([-0.1, 1.1])
axs[0][1].set_xlabel('假阳率', fontproperties=font)
axs[0][1].set_ylabel('真阳率', fontproperties=font)
axs[0][1].set_title('修改参数决策树ROC曲线', fontproperties=font)
axs[0][1].legend(loc="upper left")

forest = RandomForestClassifier()
forest.fit(x_train, y_train)
fpr, tpr, th4 = metrics.roc_curve(y_test, forest.predict_proba(x_test.values)[:, 1])
roc_auc = metrics.auc(fpr, tpr)
print(f'默认参数随机森林roc_auc={roc_auc}')
axs[1][0].plot(fpr, tpr, color='b', lw=2, label='ROC curve (area = %f)' % roc_auc)
axs[1][0].plot([0, 1], [0, 1], color='r', lw=2, linestyle='--')
axs[1][0].set_xlim([-0.1, 1.1])
axs[1][0].set_ylim([-0.1, 1.1])
axs[1][0].set_xlabel('假阳率', fontproperties=font)
axs[1][0].set_ylabel('真阳率', fontproperties=font)
axs[1][0].set_title('默认参数随机森林ROC曲线', fontproperties=font)
axs[1][0].legend(loc="upper left")

forest1 = RandomForestClassifier(n_estimators=100, max_depth=20, min_samples_leaf=100, random_state=11223)
forest1.fit(x_train, y_train)
fpr, tpr, th5 = metrics.roc_curve(y_test, forest1.predict_proba(x_test.values)[:, 1])
roc_auc = metrics.auc(fpr, tpr)
print(f'修改参数随机森林roc_auc={roc_auc}')
axs[1][1].plot(fpr, tpr, color='b', lw=2, label='ROC curve (area = %f)' % roc_auc)
axs[1][1].plot([0, 1], [0, 1], color='r', lw=2, linestyle='--')
axs[1][1].set_xlim([-0.1, 1.1])
axs[1][1].set_ylim([-0.1, 1.1])
axs[1][1].set_xlabel('假阳率', fontproperties=font)
axs[1][1].set_ylabel('真阳率', fontproperties=font)
axs[1][1].set_title('修改参数随机森林ROC曲线', fontproperties=font)
axs[1][1].legend(loc="upper left")
plt.show()
